package de.ubschmidt.capi;

import de.ubschmidt.capi.util.Bits;
import java.nio.ByteBuffer;

/**
 * The parameter <b>Info mask</b> specifies which type of information for
 * a physical connection or controller is provided by COMMON-ISDN-API.
 *
 * <p>The selected information is indicated in INFO_IND
 * messages to the application. A given Info mask (set in LISTEN_REQ)
 * is valid until it is superseded by another LISTEN_REQ, and applies to
 * all information concerning the corresponding application. The Info
 * mask is coded as a bit field. A bit set to 1 means that corresponding
 * INFO_IND messages are generated. A bit set to 0 means the specified
 * information is suppressed. In the default Info mask, all bits are
 * set to 0. If an application wants to change this value, it must
 * send a LISTEN_REQ message, even if it does not want to be informed
 * about incoming calls.
 */
public class InfoMask
        implements ByteBufferWritable {
    /** The binary representation of this {@code InfoMask}. */
    private int _infoMask = 0;

    /**
     * Creates a new, empty {@code InfoMask}.
     */
    public InfoMask() {
    }

    /**
     * Sets the specified bit within the InfoMask.
     *
     * @param infoMaskBit The InfoMaskBit to set.
     */
    public void set(final InfoMaskBit infoMaskBit) {
        _infoMask = Bits.setBit(_infoMask, infoMaskBit.getValue());
    }

    /**
     * Set all known bits within the InfoMask.
     *
     * Reserved bits
     */
    public void setAll() {
        set(InfoMaskBit.CAUSE);
        set(InfoMaskBit.DATE_TIME);
        set(InfoMaskBit.DISPLAY);
        set(InfoMaskBit.USER_USER);
        set(InfoMaskBit.CALL_PROGRESS);
        set(InfoMaskBit.FACILITY);
        set(InfoMaskBit.CHARGE_INFORMATION);
        set(InfoMaskBit.CALLED_PARTY_NUMBER);
        set(InfoMaskBit.CHANNEL_IDENTIFICATION);
        set(InfoMaskBit.EARLY_B3_CONNECT);
        set(InfoMaskBit.REDIRECT_INFORMATION);
        set(InfoMaskBit.SENDING_COMPLETE);
    }

    /**
     * Clears the specified bit within the InfoMask.
     *
     * @param infoMaskBit The InfoMaskBit to clear.
     */
    public void clear(final InfoMaskBit infoMaskBit) {
        _infoMask = Bits.clearBit(_infoMask, infoMaskBit.getValue());
    }

    /**
     * Clears all bits within the InfoMask.
     */
    public void clearAll() {
        _infoMask = 0;
    }

    /**
     * Test for the specified InfoMaskBit.
     *
     * @param infoMaskBit The InfoMaskBit to test.
     * @return True, if the specified bit is set, otherwise false.
     */
    public boolean isSet(final InfoMaskBit infoMaskBit) {
        return Bits.isBitSet(_infoMask, infoMaskBit.getValue());
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();

        sb.append(getClass().getSimpleName());
        sb.append("[");

        InfoMaskBit [] infoMaskBits = InfoMaskBit.values();
        boolean needSeparator = false;

        for (int i = 0; i < infoMaskBits.length; ++i) {
            if (Bits.isBitSet(_infoMask, infoMaskBits[i].getValue())) {
                if (needSeparator) {
                    sb.append(" ");
                }

                sb.append(infoMaskBits[i]);
                needSeparator = true;
            }
        }

        sb.append("]");

        return sb.toString();
    }

    /** {@inheritDoc} */
    public void writeTo(final ByteBuffer byteBuffer) {
        byteBuffer.putInt(_infoMask);
    }
}
